home *** CD-ROM | disk | FTP | other *** search
/ Dr. Windows 3 / dr win3.zip / dr win3 / PVDRIVER / MACFONTX.ZIP / XBIN23.ZIP / XBIN.C < prev    next >
C/C++ Source or Header  |  1991-01-13  |  19KB  |  900 lines

  1. #ifndef lint
  2. static char version[] = "xbin.c Version 2.3 09/30/85";
  3. #endif lint
  4.  
  5. #include <stdio.h>
  6. #include <sys/types.h>
  7. #include <sys/stat.h>
  8. #ifndef MSDOS
  9. #include <sys/dir.h>
  10. #endif
  11.  
  12. #ifndef MSDOS
  13. #ifdef MAXNAMLEN    /* 4.2 BSD */
  14. #define FNAMELEN MAXNAMLEN
  15. #else
  16. #define FNAMELEN DIRSIZ
  17. #endif
  18. #else
  19. #define FNAMELEN 8
  20. #endif
  21.  
  22. #ifdef BSD
  23. #include <sys/time.h>
  24. #include <sys/timeb.h>
  25. #define search_last rindex
  26. extern char *rindex();
  27. #else
  28. #include <time.h>
  29. extern long timezone;
  30. #define search_last strrchr
  31. extern char *strrchr();
  32. #endif
  33.  
  34. /* Mac time of 00:00:00 GMT, Jan 1, 1970 */
  35. #define TIMEDIFF 0x7c25b080
  36.  
  37. #define DATABYTES 128
  38.  
  39. #define BYTEMASK 0xff
  40. #define BYTEBIT 0x100
  41. #define WORDMASK 0xffff
  42. #define WORDBIT 0x10000
  43.  
  44. #define NAMEBYTES 63
  45. #define H_NLENOFF 1
  46. #define H_NAMEOFF 2
  47.  
  48. /* 65 <-> 80 is the FInfo structure */
  49. #define H_TYPEOFF 65
  50. #define H_AUTHOFF 69
  51. #define H_FLAGOFF 73
  52.  
  53. #define H_LOCKOFF 81
  54. #define H_DLENOFF 83
  55. #define H_RLENOFF 87
  56. #define H_CTIMOFF 91
  57. #define H_MTIMOFF 95
  58.  
  59. #define H_OLD_DLENOFF 81
  60. #define H_OLD_RLENOFF 85
  61.  
  62. #define F_BUNDLE 0x2000
  63. #define F_LOCKED 0x8000
  64.  
  65. struct macheader {
  66.     char m_name[NAMEBYTES+1];
  67.     char m_type[4];
  68.     char m_author[4];
  69.     short m_flags;
  70.     long m_datalen;
  71.     long m_rsrclen;
  72.     long m_createtime;
  73.     long m_modifytime;
  74. } mh;
  75.  
  76. struct filenames {
  77.     char f_info[256];
  78.     char f_data[256];
  79.     char f_rsrc[256];
  80. } files;
  81.  
  82. int pre_beta;    /* options */
  83. int listmode;
  84. int verbose;
  85.  
  86. int compressed;    /* state variables */
  87. int qformat;
  88. FILE *ifp;
  89.  
  90. /*
  91.  * xbin -- unpack BinHex format file into suitable
  92.  * format for downloading with macput
  93.  * Dave Johnson, Brown University Computer Science
  94.  *
  95.  * (c) 1984 Brown University
  96.  * may be used but not sold without permission
  97.  *
  98.  * created ddj 12/16/84
  99.  * revised ddj 03/10/85 -- version 4.0 compatibility, other minor mods
  100.  * revised ddj 03/11/85 -- strip LOCKED bit from m_flags
  101.  * revised ahm 03/12/85 -- System V compatibility
  102.  * revised dba 03/16/85 -- (Darin Adler, TMQ Software)  4.0 EOF fixed,
  103.  *               4.0 checksum added
  104.  * revised ddj 03/17/85 -- extend new features to older formats: -l, stdin
  105.  * revised ddj 03/24/85 -- check for filename truncation, allow multiple files
  106.  * revised ddj 03/26/85 -- fixed USG botches, many problems w/multiple files
  107.  * revised jcb 03/30/85 -- (Jim Budler, amdcad!jimb), revised for compatibility
  108.  *               with 16-bit int machines
  109.  * revised dl  06/16/85 -- (Dan LaLiberte, liberte@uiucdcs) character
  110.  *               translation speedup
  111.  * revised ddj 09/30/85 -- fixed problem with run of RUNCHAR
  112.  */
  113. char usage[] = "usage: \"xbin [-v] [-l] [-o] [-n name] [-] filename\"\n";
  114.  
  115. main(ac, av)
  116. char **av;
  117. {
  118.     char *filename, *macname;
  119.  
  120.     filename = ""; macname = "";
  121.     ac--; av++;
  122.     while (ac) {
  123.         if (av[0][0] == '-') {
  124.             switch (av[0][1]) {
  125.             case '\0':
  126.                 filename = "-";
  127.                 break;
  128.             case 'v':
  129.                 verbose++;
  130.                 break;
  131.             case 'l':
  132.                 listmode++;
  133.                 break;
  134.             case 'o':
  135.                 pre_beta++;
  136.                 break;
  137.             case 'n':
  138.                 if (ac > 1) {
  139.                     ac--; av++;
  140.                     macname = av[0];
  141.                     filename = "";
  142.                     break;
  143.                 }
  144.                 else
  145.                     goto bad_usage;
  146.             default:
  147.                 goto bad_usage;
  148.             }
  149.         }
  150.         else
  151.             filename = av[0];
  152.         if (filename[0] != '\0') {
  153.             setup_files(filename, macname);
  154.             if (listmode) {
  155.                 print_header();
  156.             }
  157.             else {
  158.                 process_forks();
  159.                 /* now that we know the size of the forks */
  160.                 forge_info();
  161.             }
  162.             if (ifp != stdin)
  163.                 fclose(ifp);
  164.             macname = "";
  165.             ifp = NULL;        /* reset state */
  166.             qformat = 0;
  167.             compressed = 0;
  168.         }
  169.         ac--; av++;
  170.     }
  171.     if (*filename == '\0') {
  172. bad_usage:
  173.         fprintf(stderr, usage);
  174.         exit(1);
  175.     }
  176. }
  177.  
  178. static char *extensions[] = {
  179.     ".hqx",
  180.     ".hcx",
  181.     ".hex",
  182.     "",
  183.     NULL
  184. };
  185.  
  186. setup_files(filename, macname)
  187. char *filename;        /* input file name -- extension optional */
  188. char *macname;        /* name to use on the mac side of things */
  189. {
  190.     char namebuf[256], *np;
  191.     char **ep;
  192.     int n;
  193.     struct stat stbuf;
  194.     long curtime;
  195.  
  196.     if (filename[0] == '-') {
  197.         ifp = stdin;
  198.         filename = "stdin";
  199.     }
  200.     else {
  201.         /* find input file and open it */
  202.         for (ep = extensions; *ep != NULL; ep++) {
  203.             sprintf(namebuf, "%s%s", filename, *ep);
  204.             if (stat(namebuf, &stbuf) == 0)
  205.                 break;
  206.         }
  207.         if (*ep == NULL) {
  208.             perror(namebuf);
  209.             exit(-1);
  210.         }
  211.         ifp = fopen(namebuf, "rt");
  212.         if (ifp == NULL) {
  213.             perror(namebuf);
  214.             exit(-1);
  215.         }
  216.     }
  217.     if (ifp == stdin) {
  218.         curtime = time(0);
  219.         mh.m_createtime = curtime;
  220.         mh.m_modifytime = curtime;
  221.     }
  222.     else {
  223.         mh.m_createtime = stbuf.st_mtime;
  224.         mh.m_modifytime = stbuf.st_mtime;
  225.     }
  226.     if (listmode || verbose) {
  227.         fprintf(stderr, "%s %s%s",
  228.             listmode ? "\nListing" : "Converting",
  229.             namebuf, listmode ? ":\n" : " ");
  230.     }
  231.  
  232.     qformat = find_header(); /* eat mailer header &cetera, intuit format */
  233.  
  234.     if (qformat)
  235.         do_q_header(macname);
  236.     else
  237.         do_o_header(macname, filename);
  238.  
  239.     /* make sure host file name doesn't get truncated beyond recognition */
  240.     n = strlen(mh.m_name);
  241.     if (n > FNAMELEN - 2)
  242.         n = FNAMELEN - 2;
  243.     strncpy(namebuf, mh.m_name, n);
  244.     namebuf[n] = '\0';
  245.  
  246.     /* get rid of troublesome characters */
  247.     for (np = namebuf; *np; np++)
  248.         if (*np == ' ' || *np == '/')
  249.             *np = '_';
  250.  
  251.     sprintf(files.f_data, "%s.data", namebuf);
  252.     sprintf(files.f_rsrc, "%s.rsrc", namebuf);
  253.     sprintf(files.f_info, "%s.info", namebuf);
  254.     if (verbose)
  255.         fprintf(stderr, "==> %s.{info,data,rsrc}\n", namebuf);
  256. }
  257.  
  258. /* print out header information in human-readable format */
  259. print_header()
  260. {
  261.     char *ctime();
  262.  
  263.     printf("macname: %s\n", mh.m_name);
  264.     printf("filetype: %.4s, ", mh.m_type);
  265.     printf("author: %.4s, ", mh.m_author);
  266.     printf("flags: 0x%x\n", mh.m_flags);
  267.     if (qformat) {
  268.         printf("data length: %ld, ", mh.m_datalen);
  269.         printf("rsrc length: %ld\n", mh.m_rsrclen);
  270.     }
  271.     if (!pre_beta) {
  272.         printf("create time: %s", ctime(&mh.m_createtime));
  273.     }
  274. }
  275.  
  276. process_forks()
  277. {
  278.     if (qformat) {
  279.         /* read data and resource forks of .hqx file */
  280.         do_q_fork(files.f_data, mh.m_datalen);
  281.         do_q_fork(files.f_rsrc, mh.m_rsrclen);
  282.     }
  283.     else
  284.         do_o_forks();
  285. }
  286.  
  287. /* write out .info file from information in the mh structure */
  288. forge_info()
  289. {
  290.     static char buf[DATABYTES];
  291.     char *np;
  292.     FILE *fp;
  293.     int n;
  294.     long tdiff;
  295.     struct tm *tp;
  296. #ifdef BSD
  297.     struct timeb tbuf;
  298. #else
  299.     long bs;
  300. #endif
  301.  
  302.     for (np = mh.m_name; *np; np++)
  303.         if (*np == '_') *np = ' ';
  304.  
  305.     buf[H_NLENOFF] = n = np - mh.m_name;
  306.     strncpy(buf + H_NAMEOFF, mh.m_name, n);
  307.     strncpy(buf + H_TYPEOFF, mh.m_type, 4);
  308.     strncpy(buf + H_AUTHOFF, mh.m_author, 4);
  309.     put2(buf + H_FLAGOFF, mh.m_flags & ~F_LOCKED);
  310.     if (pre_beta) {
  311.         put4(buf + H_OLD_DLENOFF, mh.m_datalen);
  312.         put4(buf + H_OLD_RLENOFF, mh.m_rsrclen);
  313.     }
  314.     else {
  315.         put4(buf + H_DLENOFF, mh.m_datalen);
  316.         put4(buf + H_RLENOFF, mh.m_rsrclen);
  317.  
  318.         /* convert unix file time to mac time format */
  319. #ifdef BSD
  320.         ftime(&tbuf);
  321.         tp = localtime(&tbuf.time);
  322.         tdiff = TIMEDIFF - tbuf.timezone * 60;
  323.         if (tp->tm_isdst)
  324.             tdiff += 60 * 60;
  325. #else
  326.         /* I hope this is right! -andy */
  327.         time(&bs);
  328.         tp = localtime(&bs);
  329.         tdiff = TIMEDIFF - timezone;
  330.         if (tp->tm_isdst)
  331.             tdiff += 60 * 60;
  332. #endif
  333.         put4(buf + H_CTIMOFF, mh.m_createtime + tdiff);
  334.         put4(buf + H_MTIMOFF, mh.m_modifytime + tdiff);
  335.     }
  336.     fp = fopen(files.f_info, "wb");
  337.     if (fp == NULL) {
  338.         perror("info file");
  339.         exit(-1);
  340.     }
  341.     fwrite(buf, 1, DATABYTES, fp);
  342.     fclose(fp);
  343. }
  344.  
  345. /* eat characters until header detected, return which format */
  346. find_header()
  347. {
  348.     int c, at_bol;
  349.     char ibuf[BUFSIZ];
  350.  
  351.     /* look for "(This file ...)" line */
  352.     while (fgets(ibuf, BUFSIZ, ifp) != NULL) {
  353.         if (strncmp(ibuf, "(This file", 10) == 0)
  354.             break;
  355.     }
  356.     at_bol = 1;
  357.     while ((c = getc(ifp)) != EOF) {
  358.         switch (c) {
  359.         case '\n':
  360.         case '\r':
  361.             at_bol = 1;
  362.             break;
  363.         case ':':
  364.             if (at_bol)    /* q format */
  365.                 return 1;
  366.             break;
  367.         case '#':
  368.             if (at_bol) {    /* old format */
  369.                 ungetc(c, ifp);
  370.                 return 0;
  371.             }
  372.             break;
  373.         default:
  374.             at_bol = 0;
  375.             break;
  376.         }
  377.     }
  378.  
  379.     fprintf(stderr, "unexpected EOF\n");
  380.     exit(2);
  381.     /* NOTRE